﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Dispatchers.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the Dispatchers type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;
    using System.Threading;
    using System.Windows.Threading;

    public static class Dispatchers
    {
        public static TReturn InvokeAndWait<TReturn>(this IDispatcher instance, Func<TReturn> func)
        {
            var result = default(TReturn);
            InvokeAndWait(instance, () =>
                {
                    result = func();
                });
            return result;
        }

        public static void InvokeAndWait(this IDispatcher instance, Action action)
        {
            if (!instance.CheckAccess())
            {
                var resetEvent = new ManualResetEvent(false);
                instance.BeginInvoke(() =>
                {
                    action();
                    resetEvent.Set();
                });
                resetEvent.WaitOne();
            }
            else
            {
                action();
            }
        }

        public static TReturn InvokeAndWait<TReturn>(this Dispatcher instance, Func<TReturn> func)
        {
            var result = default(TReturn);
            InvokeAndWait(instance, () =>
                {
                    result = func();
                });
            return result;
        }
        
        public static void InvokeAndWait(this Dispatcher instance, Action action)
        {
            if (!instance.CheckAccess())
            {
                var resetEvent = new ManualResetEvent(false);
                Action actionWrapper =
                    () =>
                        {
                            action();
                            resetEvent.Set();
                        };
                instance.BeginInvoke(actionWrapper);
                resetEvent.WaitOne();
            }
            else
            {
                action();
            }
        }
    }
}
